import os
import base64
import codecs
import ctypes
import datetime
import json
import hashlib
import multiprocessing
import inspect

from django.http.response import JsonResponse
from django.http import StreamingHttpResponse
from django.db.utils import IntegrityError
from django.db.models import Q
from django import forms
from django.conf import settings
from django.utils.html import format_html
from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError

import xadmin
from xadmin import views
from xadmin.layout import Fieldset, Main, Side, Row, TabHolder, Tab, Field

from .models import ClientInfo, DeviceInfo, DeviceTypeInfo, CertificationInfo
from nesun_cert_web.base_adminx import ThemeSetting, CustomView

# Register your models here.
# class CertificationInfoInline:
#     model = CertificationInfo
#     extra = 0
#     exclude = ("value", "start_time", "end_time", "add_time", )
#     verbose_name = verbose_name_plural = "用户历史认证信息"

#     def get_form_layout(self):
#         if self.org_obj:
#             self.form_layout = (
#                 Fieldset("授权时间信息", Row("duration")),
#                 Fieldset("授权状态信息", Row("status", "is_expired"))
#             )

#         return super().get_form_layout()
# @xadmin.sites.register(views.website.IndexView)
# class MainDashboard(object):
#     widgets = [
#         [
#             {"type": "html", "title": "Title Widget",
#              "content": "<h3></h3><p>Join Online Group: <br/>QQ Qun : 282936295</p>"},
#             {"type": "chart", "model": "app.accessrecord", "chart": "user_count",
#              "params": {"_p_date__gte": "2013-01-08", "p": 1, "_p_date__lt": "2013-01-29"}},
#             {"type": "list", "model": "app.host", "params": {"o": "-guarantee_date"}},
#         ],
#         [
#             {"type": "qbutton", "title": "Quick Start",
#              "btns": [{"model": Host}, {"model": IDC}, {"title": "Google", "url": "http://www.google.com"}]},
#             {"type": "addform", "model": MaintainLog},
#         ]
#     ]


LIB = ctypes.CDLL(os.path.join(settings.LIB_PATH, "auth.so"))
decrypt = LIB.Decrypt
decrypt.restype = ctypes.c_char_p
decrypt.argtypes = [ctypes.c_char_p]


class BaseAdminx:
    list_export = ("csv", "xml", "json",)
    list_per_page = 30


class DeviceInfoInline:
    model = DeviceInfo
    extra = 0
    verbose_name = verbose_name_plural = "客户设备信息"
    # style = "defa"


# class CertForm(forms.ModelForm):
#     certification = forms.ModelChoiceField(queryset="SELECT ")
#     class Meta:
#         model = ClientInfo


@xadmin.sites.register(ClientInfo)
class ClientInfoAdmin(BaseAdminx):
    list_display = ("id", "name", "colored_status", "add_time", "seller",)
    list_display_links = ("name",)
    list_editable = ("name",)
    list_filter = ("name", "status",)
    search_fields = ('name',)
    readonly_fields = ('id', 'add_time', "update_time",)
    date_hierarchy = 'add_time'

    reversion_enable = True

    inlines = (DeviceInfoInline,)

    model_icon = "fa fa-user"

    def get_form_layout(self):
        self.form_layout = (
            Main(
                Fieldset(_('用户基本信息'), 'name', Row('contact', 'region')),
            ),
            Side(
                Fieldset(_('其他信息'), 'status', 'add_time', "update_time", )
            )
        )

        return super().get_form_layout()

    def get_readonly_fields(self):
        if self.user.is_superuser:
            self.readonly_fields = []
        return self.readonly_fields


@xadmin.sites.register(DeviceTypeInfo)
class DeviceTypeInfoAdmin(BaseAdminx):
    list_display = ("id", "type_name", "add_time",)
    list_editable = ("type_name", )
    list_filter = ("type_name", )
    search_fields = ("type_name", )
    readonly_fields = ("add_time", )

    model_icon = "fa fa-book"


@xadmin.sites.register(DeviceInfo)
class DeviceInfoAdmin(BaseAdminx):
    list_display = ("id", "device_id", "client", "type", "is_banned", "add_time",)
    list_display_links = ("device_id",)
    list_editable = ("is_banned",)
    list_filter = ("client", "is_banned",)
    search_fields = ("client",)
    readonly_fields = ("device_id", "device_cpu", "device_mac", "device_board", "add_time", "update_time",)

    relfield_style = "fk-select"
    reversion_enable = True

    def get_form_layout(self):
        self.form_layout = (
            Main(
                Fieldset(_('设备识别信息'), 'device_id'),
                Fieldset(_('设备基本信息'),
                         Row('device_cpu', 'device_mac'),
                         Row('device_board', 'device_mid')),
                Fieldset(_('关联设备信息'), 'client')
            ),
            Side(
                Fieldset(_('其他信息'), 'is_banned', 'add_time', "update_time", )
            )
        )

        return super().get_form_layout()

    def get_readonly_fields(self):
        if self.user.is_superuser:
            self.readonly_fields = ('device_id', 'add_time',)
        return self.readonly_fields

    model_icon = "fa fa-desktop"


@xadmin.sites.register(CertificationInfo)
class CertificationInfoAdmin(BaseAdminx):
    list_display = ("id", "device", "start_time", "end_time", "duration", "status", 'is_expired',)
    list_display_links = ("device",)
    list_editable = ('duration',)
    readonly_fields = ('value', 'start_time', 'add_time', 'update_time',)
    exclude = ('start_time', 'end_time', )

    fieldsets = ('all', )

    relfield_style = "fk-select"
    reversion_enable = True

    def get_readonly_fields(self):
        if self.org_obj and self.org_obj.value is not None:
            self.readonly_fields = ('value', 'add_time', 'update_time', 'device', )
        return self.readonly_fields

    def get_form_layout(self):
        if self.org_obj:
            # self.form_layout = (
            #     Main(
            #         _('授权信息'),
            #         TabHolder(
            #             Tab('自动授权',
            #                 Field('value'),
            #                 Field('duration'),
            #                 Field('device'),
            #                 css_class='unsort',
            #                 css_id='auto'
            #                 ),
            #             Tab('手动授权',
            #                 Field('value'),
            #                 Field('duration'),
            #                 Field('device'),
            #                 Field('cert_file'),
            #                 Field('cert_code', css_class='extra'),
            #                 css_class='unsort',
            #                 css_id='manual'
            #                 )
            #         )
            #     ),
            #     Side(
            #         Fieldset(
            #             _('其他信息'),
            #             'add_time', 'update_time',
            #             'is_expired', 'status',
            #         )
            #     )
            # )
            self.form_layout = (
                Main(
                    _('授权信息'),
                    Fieldset(_('激活信息'), 'value'),
                    Fieldset(_('授权时间信息'), 'duration'),
                    Fieldset(_('授权设备信息'), 'device'),
                    Fieldset(_('手动授权信息'), 'cert_file', 'cert_code'),
                ),
                Side(
                    Fieldset(
                        _('其他信息'),
                        'add_time', 'update_time',
                        'is_expired', 'status',
                    )
                )
            )

        return super().get_form_layout()

    def save_models(self):
        super().save_models()
        obj = self.new_obj
        if obj.value is None and obj.cert_file is not None:
            # 说明使用手动授权
            manager = multiprocessing.Manager()
            return_dict = manager.dict()
            p = multiprocessing.Process(target=get_info_worker, args=(obj.cert_file.name, return_dict))
            p.start()
            p.join()
            value = return_dict.get("value")

            if value:
                info = eval(value.decode())
                client_name = info.get('Name')
                client_reg = info.get('Region')
                client_con = info.get('Contact')
                cpu_info = info.get('Cpu')
                mac_addr = info.get('Mac')
                board_info = info.get('Board')
                machine_id = info.get('MachineId')
                start_time = info.get('StartTime')

                if not client_name or not cpu_info or not mac_addr or not board_info or not machine_id:
                    print("No sufficient fields!")
                    self.message_user('没有足够的信息！', 'error')
                    return

                client = obj.device.client

                if not client:
                    self.message_user('没有查找到客户信息！', 'error')
                    return

                print("CLIENT:", client)
                client.contact = client_con
                client.region = client_reg

                device = obj.device

                if not device:
                    print("没有设备信息，请联系管理员！")
                    self.message_user('没有设备信息！', 'error')
                    return

                device.device_cpu = cpu_info
                device.device_mac = mac_addr
                device.device_board = board_info
                device.device_mid = machine_id
                device.client = client

                duration = obj.duration
                cert_code = get_certification_code(start_time, str(duration), mac_addr, cpu_info, board_info,
                                                   machine_id)

                obj.value = cert_code
                obj.start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d')
                print("CERT:", obj)

                data = {
                    "Certification": cert_code,
                    "Duration": duration,
                    "Manual": "true"
                }

                code = json.dumps(data)
                bcode = base64.b64encode(code.encode())

                obj.cert_code = bcode.decode()

                client.save()

                try:
                    device.save()
                except IntegrityError:
                    self.message_user('设备已存在！', 'error')
                    return
                except Exception:
                    self.message_user('未知错误！', 'error')
                    return

                try:
                    obj.save()
                except IntegrityError:
                    self.message_user('设备已存在！', 'error')
                    return
                except Exception:
                    self.message_user('未知错误！', 'error')
                    return
        else:
            super().save_models()

    model_icon = "fa fa-briefcase"


def get_info_worker(filename:str, return_dict:dict):
    value = decrypt(filename.encode())
    return_dict.update({"value": value})


def get_certification_code(start_time: str, duration: str, mac_addr: str, cpu_info: str, board_info: str,
                            mid: str) -> str:
    """获取授权码，授权码长度为 512 bits，128 位 HEX 字符"""
    sha = hashlib.sha512()
    info = "|".join([mid, mac_addr, cpu_info, board_info, start_time, duration])
    sha.update(codecs.encode(info))
    return sha.hexdigest()
